﻿using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Windows;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Navigation;
using System.Windows.Threading;

namespace CrackNET
{
    // *******************************************************************************************
    // NOTE: A lot of the code in this file came from Pete Blois's excellent utility called Snoop.
    // You can download Snoop, the runtime WPF application viewer, here: http://blois.us/Snoop/
    // I am using Mr. Blois's code with his permission.
    // - Josh Smith 10/2008
    // *******************************************************************************************

    public partial class MainWindow : Window
    {
        #region Fields

        readonly ObservableCollection<WindowInfo> _windows;
        readonly ICollectionView _windowsView;

        #endregion // Fields

        #region Constructor

        public MainWindow()
        {
            InitializeComponent();

#if DEBUG
            this.Topmost = false;
#else
            this.Topmost = true;
#endif

            _windows = new ObservableCollection<WindowInfo>();
            this.windowsCombo.ItemsSource = _windows;
            _windowsView = CollectionViewSource.GetDefaultView(_windows);
            _windowsView.SortDescriptions.Add(new SortDescription("Description", ListSortDirection.Ascending));
            _windowsView.CurrentChanged += delegate { this.crackItButton.IsEnabled = _windowsView.CurrentItem != null; };
            this.windowsCombo.Focus();

            this.Refresh();
            this.MouseDown += this.OnMouseDown;
        }

        #endregion // Constructor

        #region Refresh

        internal void Refresh()
        {
            _windows.Clear();

            foreach (IntPtr windowHandle in NativeMethods.ToplevelWindows)
            {
                WindowInfo window = new WindowInfo(windowHandle);
                if (window.IsValidProcess && !this.HasProcess(window.OwningProcess))
                    _windows.Add(window);
            }

            _windowsView.MoveCurrentToFirst();
        }

        #endregion // Refresh

        #region Event Handling Methods

        void OnMouseDown(object sender, MouseButtonEventArgs e)
        {
            if (e.LeftButton == MouseButtonState.Pressed)
                this.DragMove();
        }

        void OnCloseButtonClick(object sender, RoutedEventArgs e)
        {
            base.Close();
        }

        void OnMinimizeButtonClick(object sender, RoutedEventArgs e)
        {
            base.WindowState = WindowState.Minimized;
        }

        void OnHyperlinkRequestNavigate(object sender, RequestNavigateEventArgs e)
        {
            try
            {
                Process.Start(e.Uri.OriginalString);
            }
            catch { }
        }

        void OnCrackItButtonClick(object sender, RoutedEventArgs e)
        {
            WindowInfo info = _windowsView.CurrentItem as WindowInfo;
            if (info == null)
                return;

            DispatcherTimer timer = new DispatcherTimer();
            timer.Interval = this.alienDude.ObservableBlinkDuration;
            timer.Tick += delegate
            {
                timer.Stop();

                // Launch the Injected Viewer in some other process.
                if (!info.Inject())
                    this.Refresh();

                base.Activate();
            };

            timer.Start();
            this.alienDude.Blink();
        }

        void OnRefreshButtonClick(object sender, RoutedEventArgs e)
        {
            this.Refresh();
        }

        #endregion // Event Handling Methods

        #region Private Helpers

        bool HasProcess(Process process)
        {
            foreach (WindowInfo window in _windows)
                if (window.OwningProcess.Id == process.Id)
                    return true;

            return false;
        }

        #endregion // Private Helpers
    }
}